/**
 * File: ContigMapper.java
 * Created by: mhaimel
 * Created on: Mar 9, 2010
 * CVS:  $Id: ContigMapper.java 1.0 Mar 9, 2010 8:54:06 AM mhaimel Exp $
 */
package uk.ac.ebi.curtain.model.graph.curtain;

import static uk.ac.ebi.curtain.utils.ArrayHelper.castArray;

import org.apache.commons.lang.StringUtils;

import uk.ac.ebi.curtain.model.graph.Graph;
import uk.ac.ebi.curtain.model.graph.NodeEdge;
import uk.ac.ebi.curtain.model.graph.io.ReadMapper;
import uk.ac.ebi.curtain.model.graph.io.WriteMapper;

/**
 * @author mhaimel
 *
 */
public class ContigMapper implements WriteMapper<ContigInfo>, ReadMapper<ContigInfo> {

	private static final char SEP_CHAR = ';';
	private static final String[] header = new String[]{
		"contig_Id","contig_Length","contig_categories","mapping_partial_start","mapping_partial_end", "mapping_full","count_sequence", "count_bp_coverage"};

	@Override
	public String[] getHeader() {
		return header;
	}

	@Override
	public Object[] toArray(ContigInfo value) {
		return new Object[]{
				value.getId(),
				value.getLength(),
				value.getCategories(),
				joinArray(value.arrayOfPartial(NodeEdge.Start)),
				joinArray(value.arrayOfPartial(NodeEdge.End)),
				joinArray(value.arrayOfFull()),
				joinArray(value.arrayOfSequenceCountCov()),
				joinArray(value.arrayOfBpCountCov()),
		};
	}

	@Override
	public int getFieldCount() {
		return header.length;
	}

	@SuppressWarnings("unchecked")
	@Override
	public ContigInfo loadValue(String[] array, int i, Graph graph) {
		Long id = Long.valueOf(array[i++]);
		Long len = Long.valueOf(array[i++]);
		Integer cat = Integer.valueOf(array[i++]);
		Integer[] partialstart = splitString(array[i++], Integer.class, cat);
		Integer[] partialend = splitString(array[i++], Integer.class, cat);
		Integer[] full = splitString(array[i++], Integer.class, cat);
		Integer[] sequCount = splitString(array[i++], Integer.class, cat);
		Long[] bpCount = splitString(array[i++], Long.class, cat);
		ContigInfo info = new ContigInfo(
				id, 
				len, 
				cat, 
				partialstart, 
				partialend, 
				full, 
				sequCount, 
				bpCount
		);
		return info;
	}
	
	private String joinArray(Object[] arr){
		return StringUtils.join(arr, SEP_CHAR);
	}
	
	private <T extends Number> T[] splitString(String val, Class<T> clazz, Integer cat){
		String[] split = splitString(val, cat);
		T[] arr = castArray(split, clazz);
		return arr;
	}
	
	private String[] splitString(String val, Integer expectedSize){
		String[] arr = StringUtils.split(val, SEP_CHAR);
		int len = arr.length;
		if(!expectedSize.equals(len)){
			throw new IllegalStateException("Expected " + expectedSize + " categories, but " + len + " found in: " + val);
		}	
		return arr;
	}
	
}
